package com.chml.service.impl;

import com.chml.dto.GradePointDto;
import com.chml.dto.ServiceRecordDto;
import com.chml.exception.FailCallException;
import com.chml.mapper.EvaluationMapper;
import com.chml.mapper.MaternityMatronBaseInfoMapper;
import com.chml.mapper.MyMapper;
import com.chml.mapper.NursingExperienceMapper;
import com.chml.pojo.Evaluation;
import com.chml.pojo.EvaluationExample;
import com.chml.pojo.NursingExperience;
import com.chml.service.EvaluationService;
import com.github.pagehelper.PageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Created by zzt on 16-9-30.
 */
@Service
@Transactional
public class EvaluationServiceImpl implements EvaluationService {
    @Resource
    EvaluationMapper mapper;
    @Resource
    NursingExperienceMapper nursingExperienceMapper;
    @Resource
    MaternityMatronBaseInfoMapper baseInfoMapper;
    @Resource
    MyMapper myMapper;

    @Override
    public int getGradeCount(int mid, int grade) {
        EvaluationExample example = new EvaluationExample();
        example.createCriteria().andMidEqualTo(mid).andGradeEqualTo(grade);
        return (int) mapper.countByExample(example);
    }

    @Override
    public int getGradeCount(int mid) {
        EvaluationExample example = new EvaluationExample();
        example.createCriteria().andMidEqualTo(mid);
        return (int) mapper.countByExample(example);
    }

    @Override
    public int deleteByMid(int mid) {
        EvaluationExample example = new EvaluationExample();
        example.createCriteria().andMidEqualTo(mid);
        return mapper.deleteByExample(example);
    }

    @Override
    public int addRecord(int mid, ServiceRecordDto recordParam) throws FailCallException {
        EvaluationExample example = new EvaluationExample();
        example.createCriteria()
                .andMidEqualTo(mid)
                .andStartLessThanOrEqualTo((new Date(recordParam.getEnd() * 1000)))
                .andEndGreaterThanOrEqualTo((new Date(recordParam.getStart() * 1000)));
        if (mapper.countByExample(example)>0) {
            throw new FailCallException("该时段内已有服务记录，请联系管理员进行处理", 202);
        }

        Evaluation evaluation = new Evaluation();
        evaluation.setMid(mid);
        evaluation.setPhone(recordParam.getPhone());
        evaluation.setAddress(recordParam.getAddress());
        evaluation.setBabyNum((byte) recordParam.getBabyNum());
        evaluation.setComment(recordParam.getComment());
        evaluation.setEmployer(recordParam.getEmployer());
        evaluation.setStart(new Date(recordParam.getStart() * 1000));
        evaluation.setEnd(new Date(recordParam.getEnd() * 1000));
        evaluation.setIdNum(recordParam.getIdNum());
        evaluation.setFamilyType(recordParam.getFamilyType());
        evaluation.setGrade(recordParam.getGrade());
        evaluation.setCreateDate(new Date());

        NursingExperience nursingExperience = nursingExperienceMapper
                .selectByPrimaryKey(baseInfoMapper.selectByPrimaryKey(mid).getNid());
        String familyType = nursingExperience.getFamilyType();
        for (String type :
                recordParam.getFamilyType().replaceAll(" ", "").trim().split(",")) {
            if (!familyType.contains(type)) {
                if (familyType.equals("[]")) {
                    nursingExperience.setFamilyType("[" + type + "]");
                } else {
                    StringBuilder builder = new StringBuilder(familyType.replaceAll(" ", "").trim());
                    builder.deleteCharAt(builder.lastIndexOf("]")).append(",").append(type).append("]");
                    nursingExperience.setFamilyType(builder.toString());
                }
            }
        }

        if (recordParam.getBabyNum() > 1)
            nursingExperience.setNumOfTwin(nursingExperience.getNumOfTwin() + 1);
        nursingExperience.setNumOfFamily(nursingExperience.getNumOfFamily() + 1);
        nursingExperienceMapper.updateByPrimaryKey(nursingExperience);
        return mapper.insert(evaluation);
    }

    @Override
    public Evaluation getRecord(Integer gid, int mid) {
        if (gid == null) {
            try {
                EvaluationExample example = new EvaluationExample();
                example.createCriteria().andMidEqualTo(mid);
                PageHelper.startPage(0, 1, "`create_date` desc");
                return mapper.selectByExample(example).get(0);
            } catch (IndexOutOfBoundsException e) {
                return null;
            }
        }
        return mapper.selectByPrimaryKey(gid);
    }

    @Override
    public List<ServiceRecordDto> getRecordsByMid(int mid, int page, int perPage, String order) {
        EvaluationExample example = new EvaluationExample();
        example.createCriteria().andMidEqualTo(mid);
        PageHelper.startPage(page, perPage, order);
        List<Evaluation> evaluations = mapper.selectByExampleWithBLOBs(example);
        return wrapEvaluationToServiceRecord(evaluations);
    }

    @Override
    public List<GradePointDto> getGradePointsByMid(int mid) {
        List<GradePointDto> gradePoints = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            gradePoints.add(new GradePointDto(i, getGradeCount(mid, i)));
        }
        return gradePoints;
    }

    @Override
    public List<Integer> getServingMonthsInYear(int mid, int year) {
        List<Integer> result = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        for (int month=0;month<12;month++) {
            if (!getRecordsByMonth(mid, year, month).isEmpty()) {
                result.add(month);
            }
        }

        return result;
    }

    @Override
    public List<ServiceRecordDto> getRecordsByMonth(int mid, int year, int month) {
        Calendar c = Calendar.getInstance();
        c.clear();
        c.set(year, month, 1);
        Date d1 = c.getTime();
        c.set(year, month + 1, 0);
        Date d2 = c.getTime();
        PageHelper.orderBy("`start` asc");
        EvaluationExample example = new EvaluationExample();
        example.createCriteria()
                .andMidEqualTo(mid)
                .andStartLessThanOrEqualTo(d2)
                .andEndGreaterThan(d1);
        List<Evaluation> evaluations = mapper.selectByExampleWithBLOBs(example);
        return wrapEvaluationToServiceRecord(evaluations);
    }

    @Override
    public String prevServingMonth(int mid, int year, int month) {
        Calendar c = Calendar.getInstance();
        c.clear();
        c.set(year, month, 1);
        List<String> temp = myMapper.selectMonthsBefore(mid, c.getTime());
        return temp.isEmpty() ? null : temp.get(0);
    }

    @Override
    public String nextServingMonth(int mid, int year, int month) {
        Calendar c = Calendar.getInstance();
        c.clear();
        c.set(year, month+1, 0);
        List<String> temp = myMapper.selectMonthsAfter(mid, c.getTime());
        return temp.isEmpty() ? null : temp.get(0);
    }

    private List<ServiceRecordDto> wrapEvaluationToServiceRecord(List<Evaluation> evaluations) {
        List<ServiceRecordDto> records = new ArrayList<>();
        for (Evaluation e :
                evaluations) {
            ServiceRecordDto record = new ServiceRecordDto();
            record.setEmployer(e.getEmployer());
            record.setIdNum(e.getIdNum());
            record.setComment(e.getComment());
            record.setAddress(e.getAddress());
            record.setBabyNum(e.getBabyNum());
            if (e.getStart() != null)
                record.setStart(e.getStart().getTime() / 1000);
            else
                record.setStart(System.currentTimeMillis() / 1000 - 24 * 3600);
            if (e.getEnd() != null)
                record.setEnd(e.getEnd().getTime() / 1000);
            else
                record.setEnd(System.currentTimeMillis() / 1000);
            record.setFamilyType(e.getFamilyType());
            record.setGrade(e.getGrade());
            record.setPhone(e.getPhone());
            record.setCreateDate(e.getCreateDate().getTime() / 1000);
            records.add(record);
        }
        return records;
    }
}
